// example3.c - Demonstrates how to use miniz.c's deflate() and inflate() functions for simple file compression.
// Public domain, May 15 2011, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
// For simplicity, this example is limited to files smaller than 4GB, but this is not a limitation of miniz.c.
#include "miniz.h"
#include <limits.h>
#include <stdint.h>
#include <stdio.h>

typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint;

#define my_max(a,b) (((a) > (b)) ? (a) : (b))
#define my_min(a,b) (((a) < (b)) ? (a) : (b))

#define BUF_SIZE (256)
static uint8 s_inbuf[BUF_SIZE];
static uint8 s_outbuf[BUF_SIZE];

uint8_t compressed_data[] = {0x78,0x01,0x6d,0xc9,0xb1,0x09,0x00,0x30,0x08,0x04,0xc0,0x3e,0x53,0x98,0xdd,0x14,0x2c,0x1e,0x1e,0x6c,0x5c,0x5f,0xb0,0x52,0xb0,0x3c,0xce,0x0d,0xa0,0x24,0x03,0xfa,0xc5,0x0f,0x04,0x07,0xd6,0x34,0x5e,0x01,0x07,0x97,0x16,0xfc};
size_t compressed_size = sizeof(compressed_data);
int compressed_data_read(uint8_t *dbuf, int offset, int size)
{
  int len = size;
  if(offset +  size > compressed_size)
    len = compressed_size - offset;
  memcpy(dbuf, compressed_data + offset, len);
  return len;
}

#if 0
int miniz_test(void)
#else
int main(int argc, char *argv[])
#endif
{
  const char *pMode;
  FILE *pInfile, *pOutfile;
  uint infile_size;
  int level = Z_BEST_COMPRESSION;
  z_stream stream;
  int p = 1;
  const char *pSrc_filename;
  const char *pDst_filename;
  long file_loc;

  printf("miniz.c version: %s\n", MZ_VERSION);

  memset(&stream, 0, sizeof(stream));
  stream.next_in = s_inbuf;
  stream.avail_in = 0;
  stream.next_out = s_outbuf;
  stream.avail_out = BUF_SIZE;
  infile_size = compressed_size;

  {
    // Decompression.
    uint infile_remaining = infile_size;

    if (inflateInit(&stream))
    {
      printf("inflateInit() failed!\r\n");
      return EXIT_FAILURE;
    }
    int offset = 0;
    for ( ; ; )
    {
      int status;
      if (!stream.avail_in)
      {
        // Input buffer is empty, so read more bytes from input file.
        uint n = my_min(BUF_SIZE, infile_remaining);

        if (compressed_data_read(s_inbuf, offset, n) != n)
        {
          printf("Failed reading from input file!\r\n");
          return EXIT_FAILURE;
        }
        offset += n;
        stream.next_in = s_inbuf;
        stream.avail_in = n;

        infile_remaining -= n;
      }

      status = inflate(&stream, Z_SYNC_FLUSH);

      if ((status == Z_STREAM_END) || (!stream.avail_out))
      {
        // Output buffer is full, or decompression is done, so write buffer to output file.
        uint n = BUF_SIZE - stream.avail_out;
        /*if (fwrite(s_outbuf, 1, n, pOutfile) != n)
        {
          printf("Failed writing to output file!\r\n");
          return EXIT_FAILURE;
        }*/
        int i = 0;
        for(i = 0; i < n; i++)
          printf("%c", s_outbuf[i]);
        stream.next_out = s_outbuf;
        stream.avail_out = BUF_SIZE;
      }

      if (status == Z_STREAM_END)
        break;
      else if (status != Z_OK)
      {
        printf("inflate() failed with status %i!\r\n", status);
        return EXIT_FAILURE;
      }
    }

    if (inflateEnd(&stream) != Z_OK)
    {
      printf("inflateEnd() failed!\r\n");
      return EXIT_FAILURE;
    }
  }
  printf("\r\nSuccess.\r\n");
  return EXIT_SUCCESS;
}
